package com.time.social.controller;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.time.social.config.SocialConfig;
import com.time.social.entity.Result;
import com.time.social.entity.SocialTokenResponse;
import com.time.social.entity.SocialUserInfo;
import com.time.social.enums.SocialTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.view.RedirectView;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * QQ登录控制器
 *
 * @author: HuangQi
 * @date: Created in 2025/01/XX
 * @description: QQ登录控制器
 */
@Slf4j
@RestController
@RequestMapping("/social/qq")
public class QQLoginController extends AbstractSocialLoginController {

    @Autowired
    private SocialConfig socialConfig;

    private final Gson gson = new Gson();

    /**
     * QQ授权URL
     */
    private static final String QQ_AUTH_URL = "https://graph.qq.com/oauth2.0/authorize";

    /**
     * QQ获取Token URL
     */
    private static final String QQ_TOKEN_URL = "https://graph.qq.com/oauth2.0/token";

    /**
     * QQ获取OpenID URL
     */
    private static final String QQ_OPENID_URL = "https://graph.qq.com/oauth2.0/me";

    /**
     * QQ获取用户信息 URL
     */
    private static final String QQ_USER_INFO_URL = "https://graph.qq.com/user/get_user_info";

    /**
     * 跳转到QQ授权页面
     */
    @GetMapping("/login")
    public RedirectView login() {
        return super.login();
    }

    /**
     * QQ回调处理
     */
    @GetMapping("/callback")
    public Result<Object> callback(@RequestParam("code") String code,
                                    @RequestParam(value = "state", required = false) String state) {
        return super.callback(code, state);
    }

    @Override
    protected String getAuthUrl(String state) {
        SocialConfig.QQConfig qqConfig = socialConfig.getQq();
        if (qqConfig == null) {
            throw new RuntimeException("QQ配置未找到");
        }

        String redirectUri = buildCallbackUrl();
        String encodedRedirectUri = URLEncoder.encode(redirectUri, StandardCharsets.UTF_8);

        // 构建授权URL
        StringBuilder url = new StringBuilder(QQ_AUTH_URL);
        url.append("?response_type=code");
        url.append("&client_id=").append(qqConfig.getAppId());
        url.append("&redirect_uri=").append(encodedRedirectUri);
        url.append("&scope=get_user_info");
        url.append("&state=").append(state);

        return url.toString();
    }

    @Override
    protected SocialTokenResponse getAccessToken(String code) {
        try {
            SocialConfig.QQConfig qqConfig = socialConfig.getQq();
            if (qqConfig == null) {
                throw new RuntimeException("QQ配置未找到");
            }

            String redirectUri = buildCallbackUrl();

            // 构建获取token的URL
            StringBuilder url = new StringBuilder(QQ_TOKEN_URL);
            url.append("?grant_type=authorization_code");
            url.append("&client_id=").append(qqConfig.getAppId());
            url.append("&client_secret=").append(qqConfig.getAppKey());
            url.append("&code=").append(code);
            url.append("&redirect_uri=").append(URLEncoder.encode(redirectUri, StandardCharsets.UTF_8));

            // 发送请求
            String response = httpGet(url.toString());
            log.info("QQ获取token响应: {}", response);

            // QQ返回的是URL参数格式，需要解析
            SocialTokenResponse tokenResponse = new SocialTokenResponse();
            if (response.contains("access_token=")) {
                String[] pairs = response.split("&");
                for (String pair : pairs) {
                    String[] keyValue = pair.split("=");
                    if (keyValue.length == 2) {
                        String key = keyValue[0];
                        String value = keyValue[1];
                        switch (key) {
                            case "access_token":
                                tokenResponse.setAccessToken(value);
                                break;
                            case "expires_in":
                                tokenResponse.setExpiresIn(Long.parseLong(value));
                                break;
                            case "refresh_token":
                                tokenResponse.setRefreshToken(value);
                                break;
                        }
                    }
                }
            } else if (response.contains("error=")) {
                // 解析错误信息
                String[] pairs = response.split("&");
                for (String pair : pairs) {
                    String[] keyValue = pair.split("=");
                    if (keyValue.length == 2) {
                        String key = keyValue[0];
                        String value = keyValue[1];
                        if ("error".equals(key)) {
                            tokenResponse.setError(value);
                        } else if ("error_description".equals(key)) {
                            tokenResponse.setErrorDescription(value);
                        }
                    }
                }
            }

            if (tokenResponse.getAccessToken() == null) {
                tokenResponse.setError("unknown");
                tokenResponse.setErrorDescription("获取token失败");
            }

            return tokenResponse;
        } catch (Exception e) {
            log.error("QQ获取access_token失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取QQ access_token失败", e);
        }
    }

    @Override
    protected SocialUserInfo getUserInfo(String accessToken) {
        try {
            // 第一步：获取openid
            String openIdUrl = QQ_OPENID_URL + "?access_token=" + accessToken;
            String openIdResponse = httpGet(openIdUrl);
            log.info("QQ获取openid响应: {}", openIdResponse);

            // QQ返回的是JSONP格式，需要提取JSON部分
            String jsonStr = openIdResponse;
            if (openIdResponse.contains("callback(")) {
                int start = openIdResponse.indexOf("(") + 1;
                int end = openIdResponse.lastIndexOf(")");
                jsonStr = openIdResponse.substring(start, end);
            }

            JsonObject openIdJson = gson.fromJson(jsonStr, JsonObject.class);
            String openId = openIdJson.has("openid") ? 
                openIdJson.get("openid").getAsString() : null;

            if (openId == null) {
                throw new RuntimeException("获取openid失败");
            }

            // 第二步：获取用户信息
            SocialConfig.QQConfig qqConfig = socialConfig.getQq();
            StringBuilder userInfoUrl = new StringBuilder(QQ_USER_INFO_URL);
            userInfoUrl.append("?access_token=").append(accessToken);
            userInfoUrl.append("&oauth_consumer_key=").append(qqConfig.getAppId());
            userInfoUrl.append("&openid=").append(openId);

            String userInfoResponse = httpGet(userInfoUrl.toString());
            log.info("QQ获取用户信息响应: {}", userInfoResponse);

            JsonObject jsonObject = gson.fromJson(userInfoResponse, JsonObject.class);
            SocialUserInfo userInfo = new SocialUserInfo();

            if (jsonObject.has("ret") && jsonObject.get("ret").getAsInt() == 0) {
                userInfo.setOpenId(openId);
                userInfo.setNickname(jsonObject.has("nickname") ? 
                    jsonObject.get("nickname").getAsString() : null);
                userInfo.setAvatar(jsonObject.has("figureurl_qq_2") ? 
                    jsonObject.get("figureurl_qq_2").getAsString() : 
                    (jsonObject.has("figureurl_qq_1") ? 
                        jsonObject.get("figureurl_qq_1").getAsString() : null));
                userInfo.setGender(jsonObject.has("gender") ? 
                    jsonObject.get("gender").getAsString() : null);
                userInfo.setLocation(jsonObject.has("province") && jsonObject.has("city") ? 
                    jsonObject.get("province").getAsString() + " " + 
                    jsonObject.get("city").getAsString() : null);
                userInfo.setRawData(userInfoResponse);
            } else {
                String errorMsg = jsonObject.has("msg") ? 
                    jsonObject.get("msg").getAsString() : "获取用户信息失败";
                throw new RuntimeException(errorMsg);
            }

            return userInfo;
        } catch (Exception e) {
            log.error("QQ获取用户信息失败: {}", e.getMessage(), e);
            throw new RuntimeException("获取QQ用户信息失败", e);
        }
    }

    @Override
    protected SocialTypeEnum getSocialType() {
        return SocialTypeEnum.QQ;
    }

    @Override
    protected String getRedirectUri() {
        return socialConfig.getQq() != null ? 
            socialConfig.getQq().getRedirectUri() : "/social/qq/callback";
    }
}

